home *** CD-ROM | disk | FTP | other *** search
/ Mac Mania 6 / MacMania 6.toast / / Tools&Utilities / EnterAct Stuff / Drag_on Modules / hAWK programs / $Whazzat < prev    next >
Text File  |  1993-04-09  |  7KB  |  265 lines

  1. #$Whazzat: undeclarate (translate to English) most C declarations.
  2. #Typically run this on one declaration at a time by
  3. #selecting the declaration in the front text window and
  4. #running this on “Front text selection”. Output is to stdout.
  5. #If you run this on several declarations at once, each declaration
  6. #(except maybe the last) should be terminated with a semicolon.
  7. #Not for function/struct/union/enum definitions, and any comments
  8. #should start and end on the same line.
  9. #
  10. #See “whazzatTest” for some example declarations.
  11. # (You can run this program on all of whazzatTest at once)
  12. #
  13. #This is good enough to untangle a great many declarations,
  14. #but not good enough to verify that a declaration is correct.
  15. #
  16. #If called from within EnterAct with a project open (and a
  17. #dictionary built for the project), type specifications are
  18. #extended to all typedefs, structs, unions, and enums defined
  19. #in the source code for your project.
  20. #For example, if your project contains a definition of NODE,
  21. #then "NODE *" appearing in a declaration will be translated
  22. # to "pointer to NODE"; if you have no proect open or NODE
  23. #cannot be found in your project dictionary, then "NODE *"
  24. #will be translated to just "pointer to", type left unspecified.
  25.  
  26. #For a (simpler) C version of this, see
  27. # "The C Programming Language" by Kernighan & Ritchie, pg 122
  28. # and "The C Answer Book" by Tondo & Gimpel, pg 140, 146
  29. # (both published by Prentice Hall)
  30.  
  31. # User’s Manual references:
  32. # «hAWK User’s Manual» «F   Running hAWK programs»
  33. # «hAWK User’s Manual» «L  5   Regular expressions»
  34. # «hAWK User’s Manual» «M  5   Built-in string and file functions»
  35. # «hAWK User’s Manual» «K  4   Built-in variables»
  36. # «hAWK User’s Manual» «K  8   Arrays»
  37. # «hAWK User’s Manual» «N   User-defined functions»
  38. # «hAWK User’s Manual» «P  3   The getline function»
  39. # «hAWK User’s Manual» «O  3   Output into files»
  40. # «hAWK User’s Manual» «Q   The hAWK function»
  41.  
  42. BEGIN {    if (ARGC != 2) # comment this out to allow multiple files (!?)
  43.             {
  44.             print "Whoa, just one little bit at a time please."
  45.             exit
  46.             }
  47.         min_line_width = 60;
  48.         #Some "enumerated" constants
  49.         NAME = 1; PARENS = 2; BRACKETS = 3; DDD = 4;
  50.         NO = 0; YES = 1; EOF = -1;
  51.         #Some keywords, associatively arrayed:
  52.         #specifiers
  53.         types["char"] = 1
  54.         types["int"] = 1
  55.         types["void"] = 1
  56.         types["long"] = 1
  57.         types["float"] = 1
  58.         types["double"] = 1
  59.         types["short"] = 1
  60.         types["..."] = 1
  61.         #qualifiers
  62.         typeq["const"] = 1
  63.         typeq["volatile"] = 1
  64.         typeq["unsigned"] = 1
  65.         typeq["signed"] = 1
  66.         typeq["struct"] = 1
  67.         typeq["union"] = 1
  68.         typeq["enum"] = 1
  69.         typeq["pascal"] = 1
  70.         typeq["Pascal"] = 1
  71.         
  72.         prevtoken = NO;
  73.         Whazzat();
  74.     }
  75.  
  76. function Whazzat()
  77.     {
  78.     while (gettoken() != EOF)
  79.         {
  80.         if (token == "extern" || token == "static")
  81.             {
  82.             gettoken();
  83.             }
  84.         datatype = token
  85.         while (typequal() == YES)
  86.             {
  87.             gettoken();
  88.             datatype = datatype " " token
  89.             }
  90.         out = ""
  91.         name = ""
  92.         dcl();
  93.         nicely_print_decl();
  94.         }
  95.     }
  96.  
  97. function dcl(    ns)
  98.     {
  99.     for (ns = 0; gettoken() == "*"; )
  100.         ++ns;
  101.     dirdcl();
  102.     while (ns-- > 0)
  103.         out = out " pointer to"
  104.     }
  105.  
  106. function dirdcl(    type)
  107.     {
  108.     
  109.     if (tokentype == "(")
  110.         {
  111.         dcl();
  112.         if (tokentype != ")")
  113.             errmsg("Error: missing )")
  114.         }
  115.     else if (tokentype == NAME)
  116.         {
  117.         if (name == "")
  118.             name = token
  119.         }
  120.     else
  121.         prevtoken = YES;
  122.     while ((type = gettoken()) == PARENS ||
  123.         type == BRACKETS || type == "(")
  124.         {
  125.         if (type == PARENS)
  126.             out = out " function returning"
  127.         else if (type == "(")
  128.             {
  129.             out = out " function expecting"
  130.             parmdcl();
  131.             out = out " and returning"
  132.             }
  133.         else
  134.             {
  135.             out = out " array" token " of"
  136.             }
  137.         }
  138.     }
  139.  
  140. function errmsg(msg)
  141.     {
  142.     prevtoken = YES
  143.     print msg
  144.     }
  145.  
  146. function parmdcl()
  147.     {
  148.     do
  149.         {
  150.         dclspec();
  151.         } while (tokentype == ",");
  152.     if (tokentype != ")")
  153.         errmsg("missing ) in parameter declaration");
  154.     }
  155.  
  156. function dclspec(    temp)
  157.     {
  158.     gettoken();
  159.     do
  160.         {
  161.         if (tokentype != NAME && tokentype != DDD)
  162.             {
  163.             prevtoken = YES
  164.             dcl();
  165.             }
  166.         else if (typespec() == YES || typequal() == YES)
  167.             {
  168.             temp = temp " " token
  169.             gettoken();
  170.             }
  171.         else #ignore it - typically a name for a parameter eg (int x, int y,...)
  172.             gettoken();# or errmsg("unknown type in parameter list");
  173.         } while (tokentype != "," && tokentype != ")");
  174.     out = out temp
  175.     if (tokentype == ",")
  176.         out = out ","
  177.     }
  178.  
  179. function typespec(    type)
  180.     {
  181.     if (token in types)
  182.         return YES;
  183.     else if ((type = lookup(token)) == 16 ||    # typedef
  184.             type == 32 || type == 64 ||            # struct, union tag
  185.             type == 128)                        # enum tag
  186.             return YES;
  187.     return NO;
  188.     }
  189.  
  190. function typequal()
  191.     {
  192.     if (token in typeq)
  193.         return YES;
  194.     return NO;
  195.     }
  196.  
  197. #Read in a line at a time, and trim tokens from
  198. #beginning of line. A bit wasteful, but time is not
  199. #critical. Type of token is returned, and placed in tokentype;
  200. #the token string is placed in token. Note no “ungetch()” is
  201. #required, because the matches go just the right distance.
  202. function gettoken()
  203.     {
  204.     if (tokentype == EOF)
  205.         return EOF;
  206.     if (prevtoken == YES)
  207.         {
  208.         prevtoken = NO
  209.         return tokentype;
  210.         }
  211.     #Get next line if needed
  212.     while (length(line) == 0)
  213.         {
  214.         if (getline line <= 0)
  215.             return tokentype = EOF;
  216.         sub(/^[ \t]+/, "", line) #null out blank line - rarely needed
  217.         sub(/^\/\*.*\*\//, "", line) #kill one-line comment
  218.         }
  219.     #remove leading white space and comments on one line
  220.     sub(/^[ \t]+/, "", line)
  221.     sub(/^\/\*.*\*\//, "", line)
  222.     
  223.     if ((match(line, /^\(\)/) && (tokentype = PARENS)) ||     # ()
  224.         (match(line, /^\(/) && (tokentype = "(")) ||    # ( etc
  225.         (match(line, /^\[([^\]])*\]/) && (tokentype = BRACKETS)) || # [...]
  226.         (match(line, /^\.\.\./) && (tokentype = DDD)) || #variable args ...
  227.         (match(line, /^[A-Za-z_][A-Za-z0-9_]*/) && (tokentype = NAME))) # a C word
  228.         {
  229.         token = substr(line, 1, RLENGTH)
  230.         line = substr(line, RLENGTH + 1)
  231.         return tokentype
  232.         }
  233.     else
  234.         {
  235.         tokentype = substr(line,1,1)
  236.         line = substr(line, 2)
  237.         return tokentype
  238.         }
  239.     }
  240.  
  241. function nicely_print_decl(        total_decl, one_line, tabber, i, len)
  242.     {
  243.     #print name ":", out, datatype  -- works, but may produce long line
  244.     #min_line_width determines rough width of long lines
  245.     total_decl = name ": " out " " datatype;
  246.     tabber = ""
  247.     while ((len = length(total_decl)) > min_line_width)
  248.         {
  249.         i = min_line_width
  250.         #Round up to nearest word end.
  251.         while (i <= len && substr(total_decl, i, 1) ~ /[A-Za-z0-9_]/)
  252.             ++i;
  253.         one_line = substr(total_decl, 1, i)
  254.         print tabber one_line
  255.         #Skip trailing space.
  256.         while (i <= len && substr(total_decl, i, 1) ~ /[^A-Za-z0-9_]/)
  257.             ++i;
  258.         total_decl = substr(total_decl, i)
  259.         if (tabber == "")
  260.             tabber = "\t"
  261.         }
  262.     if (total_decl != "")
  263.         print tabber total_decl;
  264.     }
  265.